package cz.proks.schoolpupilbook.gwt.widget.common;

import java.util.Date;
import java.util.LinkedList;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

import cz.proks.schoolpupilbook.gwt.core.ResultNotifiable;
import cz.proks.schoolpupilbook.gwt.core.SchoolPupilBookFactory;
import cz.proks.schoolpupilbook.gwt.service.ListService;
import cz.proks.schoolpupilbook.gwt.service.ServiceFactory;
import cz.proks.schoolpupilbook.shared.domain.Course;
import cz.proks.schoolpupilbook.shared.domain.User;

public class MarkForm extends Composite {

	private static MarkFormUiBinder uiBinder = GWT.create(MarkFormUiBinder.class);

	interface MarkFormUiBinder extends UiBinder<Widget, MarkForm> {
	}
		
	@UiField Errors errors;
	@UiField Grid table;
	@UiField TextBox idBox;
	@UiField TextBox timeBox;
	@UiField ListBox lectorListBox;
	@UiField ListBox courseListBox;
	@UiField ListBox studentListBox;
	@UiField TextBox markBox;
	@UiField TextArea initialCommentArea;
	
	private final DateTimeFormat timeFormater = DateTimeFormat.getFormat("dd.MM.yyyy HH:mm");

	public MarkForm() {
		initWidget(uiBinder.createAndBindUi(this));
				
		setTimeReadOnly(true);
		setStudentListReadOnly(true);
		setMarkReadOnly(true);		
		
		courseListBox.addChangeHandler(new ChangeHandler() {			
			@Override
			public void onChange(ChangeEvent event) {
				listStudentsForCourse();
			}
		});
	}
		
	private void listStudentsForCourse() {
		ListService listService = ServiceFactory.getListService();
		listService.listStudents(getCourseId(), new ResultNotifiable<LinkedList<User>>() {					
			@Override
			public void onSucces(LinkedList<User> object) {
				setStudents(object);
				setStudentListReadOnly(false);
				setMarkReadOnly(false);
				
			}
			
			@Override
			public void onError(Throwable t) {
				Window.alert("Communication failed: " + t.getLocalizedMessage());
			}
		});				
	}
		
	
	public String getId() {
		return idBox.getValue();
	}
	
	public void setId(String id) {
		this.idBox.setValue(id);
	}
	
	public Date getTime() {
		return timeBox.getValue() == null ? null : timeFormater.parse(timeBox.getValue());
	}
	
	public void setTime(Date time) {
		timeBox.setValue(timeFormater.format(time));
	}	
	
	public void setLectors(LinkedList<User> lectorList) {
		lectorListBox.clear();
		
		if (lectorList != null)
			for (User user : lectorList) {
				lectorListBox.addItem(user.getFullName(), user.getId());
			}
		
		lectorListBox.setSelectedIndex(0);
	}
	
	public String getLectorId() {
		int i = lectorListBox.getSelectedIndex();
		return i < 0 ? null : lectorListBox.getValue(i);
	}
	
	public void setLectorId(String id) {
		int itemCount = lectorListBox.getItemCount();
		for (int i = 0; i < itemCount; i++) {
			if (lectorListBox.getValue(i).equals(id)) {
				lectorListBox.setSelectedIndex(i);
				break;
			}
		}
	}
	
	public void setCourses(LinkedList<Course> courseList) {
		courseListBox.clear();
		
		if (courseList != null) {
			for (Course course : courseList) {
				courseListBox.addItem(course.getCode(), course.getId());
			}
			
			if (!courseList.isEmpty()) {
				courseListBox.setSelectedIndex(0);
				listStudentsForCourse();
			}
			
		}				
	}
	
	public String getCourseId() {
		int i = courseListBox.getSelectedIndex();
		return i < 0 ? null : courseListBox.getValue(i);
	}
	
	public void setCourseId(String id) {
		int itemCount = courseListBox.getItemCount();
		for (int i = 0; i < itemCount; i++) {
			if (courseListBox.getValue(i).equals(id)) {
				courseListBox.setSelectedIndex(i);
				break;
			}
		}
	}
	
	public void setStudents(LinkedList<User> studentList) {
		studentListBox.clear();
		
		if (studentList != null)
			for (User user : studentList) {
				studentListBox.addItem(user.getFullName(), user.getId());
			}
		
		studentListBox.setSelectedIndex(0);
	}
	
	public String getStudentId() {
		int i = studentListBox.getSelectedIndex();
		return i < 0 ? null : studentListBox.getValue(i);
	}
	
	public void setStudentId(String id) {
		int itemCount = studentListBox.getItemCount();
		for (int i = 0; i < itemCount; i++) {
			if (studentListBox.getValue(i).equals(id)) {
				studentListBox.setSelectedIndex(i);
				break;
			}
		}
	}
	
	public String getMark() {
		return markBox.getValue();		
	}
	
	public void setMark(String mark) {
		markBox.setValue(mark);
	}
	
	public String getInitialComment() {
		return initialCommentArea.getValue();
	}
	
	public void setInitialComment(String initialComment) {
		initialCommentArea.setValue(initialComment);
	}
	
	public void setIdReadOnly(boolean value) {
		idBox.setReadOnly(value);
	}
	
	public void setTimeReadOnly(boolean value) {
		timeBox.setReadOnly(value);
	}
	
	public void setLectorListReadOnly(boolean value) {
		lectorListBox.setEnabled(!value);
	}
	
	public void setCourseListReadOnly(boolean value) {
		courseListBox.setEnabled(!value);
	}
	
	public void setStudentListReadOnly(boolean value) {
		studentListBox.setEnabled(!value);
	}
	
	public void setMarkReadOnly(boolean value) {
		markBox.setReadOnly(value);
	}
	
	public void setInitialCommentReadOnly(boolean value) {
		initialCommentArea.setReadOnly(value);
	}
	
	@UiHandler("submitButton")
	public void submit(ClickEvent event) {
		LinkedList<String> errors = validate();
		if (errors.isEmpty()) {
			this.errors.setErrors(null);
			SubmitEvent submitEevent = new SubmitEvent(getId(), getTime(), getLectorId(), getCourseId(), getStudentId(), getMark(), getInitialComment());
			SchoolPupilBookFactory.getEventBus().fireEvent(submitEevent);			
		} else {
			this.errors.setErrors(errors);			
		}
	}
	
	@UiHandler("backButton")
	public void back(ClickEvent event) {
		History.back();
	}
	
	private LinkedList<String> validate() {
		LinkedList<String> errors = new LinkedList<String>();
				
		if (getTime()== null)
			errors.add("Time field is empty");
		
		if (getLectorId() == null || getLectorId().isEmpty()) 
			errors.add("No lector selected");
		
		if(getCourseId() == null || getCourseId().isEmpty())
			errors.add("No course selected");
		
		if (getStudentId() == null || getStudentId().isEmpty())
			errors.add("No student selected");
		
		if (getMark() == null || getMark().isEmpty())
			errors.add("Mark field is empty");		
		
		return errors;
	}
	
	public static class SubmitEvent extends GwtEvent<SubmitEvent.SubmitEventHandler> {
		public interface SubmitEventHandler extends EventHandler {
			void onSubmit(SubmitEvent event);
		}
		
		public final static Type<SubmitEvent.SubmitEventHandler> TYPE = new Type<SubmitEvent.SubmitEventHandler>();
		
		private String id;
		private Date time;
		private String lectorId;
		private String courseId;
		private String studentId;
		private String mark;
		private String initialComment;
				
		public SubmitEvent(String id, Date time, String lectorId,
				String courseId, String studentId, String mark,
				String initialComment) {
			super();
			this.id = id;
			this.time = time;
			this.lectorId = lectorId;
			this.courseId = courseId;
			this.studentId = studentId;
			this.mark = mark;
			this.initialComment = initialComment;
		}

		@Override
		public Type<SubmitEventHandler> getAssociatedType() {
			return TYPE;
		}

		@Override
		protected void dispatch(SubmitEventHandler handler) {
			handler.onSubmit(this);			
		}

		public String getId() {
			return id;
		}

		public Date getTime() {
			return time;
		}

		public String getLectorId() {
			return lectorId;
		}

		public String getCourseId() {
			return courseId;
		}

		public String getStudentId() {
			return studentId;
		}

		public String getMark() {
			return mark;
		}

		public String getInitialComment() {
			return initialComment;
		}
	}

}
